package Services;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import java.util.HashMap;
import java.util.Map;


import javax.crypto.Mac;
import javax.crypto.SecretKey;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.repackaged.com.google.common.util.Base64;
import com.google.appengine.repackaged.com.google.common.util.Base64DecoderException;


import com.google.appengine.repackaged.org.json.JSONException;
import com.google.appengine.repackaged.org.json.JSONObject;

public class SignedRequestDecoder {

	  public static byte[] base64_url_decode(String input,HttpServletResponse response) throws IOException {
	    try {
			return Base64.decode(input);
		} catch (Base64DecoderException e1) {
			// TODO Auto-generated catch block
			//e1.printStackTrace();
			response.setContentType("text/plain");
			PrintWriter writer = null;
			try {
				writer = response.getWriter();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			writer.println("error in base64_url_decode :" + e1);
			writer.close();
		}
		return null;
	  }

	  public static Map parse_signed_request(String input, String secret,HttpServletResponse response) throws Exception {
	    return parse_signed_request(input, secret, 3600,response);
	  }

	  public static Map parse_signed_request(String input, String secret, int max_age,HttpServletResponse response) throws Exception {
	    String[] split = input.split("[.]", 2);

	    String encoded_sig = split[0];
	    String encoded_envelope = split[1];
	    
	    
	    String DecMsg = new String(base64_url_decode(encoded_envelope,response));
	    
	    Map envelope = getMapOfJsonString(DecMsg,response);
	    

	    String algorithm = (String) envelope.get("algorithm");

	    if (!algorithm.equals("AES-256-CBC HMAC-SHA256") && !algorithm.equals("HMAC-SHA256")) {
	      throw new Exception("Invalid request. (Unsupported algorithm.)");
	    }

//	    if (((Long) envelope.get("issued_at")) < System.currentTimeMillis() / 1000 - max_age) {
//	        throw new Exception("Invalid request. (Too old.)");
//	      }
//	    
	    byte[] key = secret.getBytes();
	    SecretKey hmacKey = new SecretKeySpec(key, "HMACSHA256");
	    Mac mac = Mac.getInstance("HMACSHA256");
	    mac.init(hmacKey);
	    byte[] digest = mac.doFinal(encoded_envelope.getBytes());

//	    if (!Arrays.equals(base64_url_decode(encoded_sig), digest)) {
//	      throw new Exception("Invalid request. (Invalid signature.)");
//	    }

	    // for requests that are signed, but not encrypted, we"re done
	    //if (algorithm.equals("HMAC-SHA256")) {
	      return envelope;
	   // }

//	    // otherwise, decrypt the payload
//	    byte[] iv = base64_url_decode((String) envelope.get("iv"));
//	    IvParameterSpec ips = new IvParameterSpec(iv);
//
//	    SecretKey aesKey = new SecretKeySpec(key, "AES");
//	    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
//	    cipher.init(Cipher.DECRYPT_MODE, aesKey, ips);
//
//	    byte[] raw_ciphertext = base64_url_decode((String) envelope.get("payload"));
//	    byte[] plaintext = cipher.doFinal(raw_ciphertext);
//	   // return (Map) parser.parse(new String(plaintext).trim());
		 // return null;
	  }

	private static Map getMapOfJsonString(String DecMsg,HttpServletResponse response) throws JSONException {
		JSONObject jsonObject = null;
	    
	    try {
			jsonObject = new JSONObject(DecMsg);
		} catch (JSONException e1) {
			// TODO Auto-generated catch block
			//e1.printStackTrace();
			response.setContentType("text/plain");
			PrintWriter writer = null;
			try {
				writer = response.getWriter();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			writer.println("error in base64_url_decode :" + e1);
			writer.close();
		}
	    
		 Map envelope = new HashMap<String, String>();
		 
		 String[] names = JSONObject.getNames(jsonObject);
		 for (String name : names) {
			 envelope.put(name, jsonObject.get(name));
			
		}
		return envelope;
	}

//	  public static void main(String[] args) throws Exception {
//		    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//String input1 = "nz7HBSCxxEz7kPb5hsKs9QDmgXdsD3xcOTb8VdktFAc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMjc4MDYwMDAsImlzc3VlZF9hdCI6MTMyNzgwMTg5Miwib2F1dGhfdG9rZW4iOiJBQUFEVnJqV1RaQmg4QkFMZmJzUFpCWVpDalpBZnl4VE5mZWNBQVVTREJVemxJSFVrc1pBclVzanJEZ1JPek11MDJ6Z0FFcExiQkRMRUh1eVVlUW1leXR1eVJXNEYyTGh1VDNFV1cxenhaQTNnWkRaRCIsInVzZXIiOnsiY291bnRyeSI6ImlsIiwibG9jYWxlIjoiZW5fVVMiLCJhZ2UiOnsibWluIjoyMX19LCJ1c2VyX2lkIjoiNjIzODkxMjAzIn0";		   
//String input = "vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0";    
//String secret = "34aa58ecb2e063c650eadc5b9983a2d7";
//		    
//			
//			Map<String, Object> jsonMap = new HashMap<String, Object>();
//			try {
//				jsonMap = parse_signed_request(input, "34aa58ecb2e063c650eadc5b9983a2d7",null);
//			} catch (Exception e1) {
//				// TODO Auto-generated catch block
//				e1.printStackTrace();
//				}
//
//				
//			//Prepare the json object we create from the request body
//			JSONObject jsonObject = null;
//			jsonObject = (JSONObject)jsonMap.get("registration");
//			
//			//getting all filled params in the registration form of the json object
//			String name = "";
//			String email = "";
//			String password = "";
//			
//			try {
//				name = (String) jsonObject.get("name");
//				email = (String) jsonObject.get("email");
//				password = (String) jsonObject.get("password");
//				
//			} catch (JSONException e) {
//				e.printStackTrace();
//			}
//			
//			String fbID = (String)jsonMap.get("user_id");
//			System.out.println();
//		    
//		  }

	}